#include "theaterconst.h"

/* TicketTaker */
void main() {
	int data;
	int i;
	int seats;
	
	init();
	
	Acquire(idMutex);
	data = ReadMonitor(ttID, 0);
	prints("TicketTaker "); print(data); prints(" has entered the theater.\n");
	SetMonitor(ttID, 0, data + 1);
	Release(idMutex);

	while (1) {
		Acquire(ttLineLock);
		if (ReadMonitor(ttBreak, data) != 0) {
			/* go on a break. wake all customers */
			SetMonitor(ttState, data, C_BREAK);
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data); 
			prints(" is going on break.\n");
			/* Release(outputLock); */
			SetMonitor(ttBreakTime, data, ReadMonitor(ttBreakTime, data) + 1);
			SetMonitor(ttLineCount, data, 0);
			Broadcast(ttLineCV[data], ttLineLock);
			Wait(ttBreakCV, ttLineLock);
			SetMonitor(ttState, data, C_BUSY);
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data); 
			prints(" is coming off break.\n");
			/* Release(outputLock); */
			SetMonitor(ttBreak, data, 0);
		}
		if (ReadMonitor(ttLineCount, data) > 0) {
			/* there's someone in line signal a customer */
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data); 
			prints(" has a line length "); print(ReadMonitor(ttLineCount, data));
			prints(" and is signaling a customer.\n");
			/* Release(outputLock); */
			SetMonitor(ttLineCount, data, ReadMonitor(ttLineCount, data) - 1);
			SetMonitor(ttState, data, C_BUSY);
			Signal(ttLineCV[data], ttLineLock);
		} else {
			/* no one in line. set ready */
			SetMonitor(ttState, data, C_READY);
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data); 
			prints(" has no one in line. I am available for a customer.\n");
			/* Release(outputLock); */
			for(i = 0; i < NUM_TICKET_TAKERS; i++) {
				if (ReadMonitor(ttStop, i) != 0) {
					SetMonitor(ttStop, i, 1);
					break;
				}
			}
		}
		Acquire(ttLock[data]);
		Release(ttLineLock);
		Wait(ttCV[data],ttLock[data]);
		Acquire(ttLineLock);
		if (ReadMonitor(ttState, data) == C_BREAK) {
			Release(ttLock[data]);
			/* waken up by manager. go on a break */
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data); 
			prints(" is going on break.\n");
			/* Release(outputLock); */

			SetMonitor(ttBreakTime, data, ReadMonitor(ttBreakTime, data) + 1);
			Wait(ttBreakCV, ttLineLock);
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data); 
			prints(" is coming off break.\n");
			/* Release(outputLock); */
			
			SetMonitor(ttState, data, C_BUSY);
			SetMonitor(ttBreak, data, 0);
			Release(ttLineLock);
			continue;
		}
		Release(ttLineLock);
		SetMonitor(ttProcess, data, 0);
		/* get ticket number */
		/* allocate seat */
		seats = ReadMonitor(ttTicket, data);
		
		/* Acquire(outputLock); */
		prints("TicketTaker "); print(data); 
		prints(" has received "); print(seats);
		prints(" tickets.\n");
		/* Release(outputLock); */
		
		Acquire(ttLineLock);
		if (ReadMonitor(ttStop, data) != 0 || seats > SEATS - ReadMonitor(ttTakenSeat, 0)) {
			/* no seats left. tell everyone in his line to wait in the lobby */
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data); 
			prints(" has received "); print(seats);
			prints(" tickets.\n");
			/* Release(outputLock); */
			
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data);
			prints(" is not allowing the group into the theater. The number of taken tickets is ");
			print(ReadMonitor(ttTakenSeat, 0)); prints(" and the group size is "); print(seats); prints(".\n");
			/* Release(outputLock); */
			SetMonitor(ttStop, data, 1);
			for(i = 0; i < NUM_TICKET_TAKERS; i++) {
				if (ReadMonitor(ttState, i) == C_READY)
				{
					SetMonitor(ttStop, i, 1);
					break;
				}
			}
			Broadcast(ttLineCV[data],ttLineLock);
			/* stop selling tickets */
			SetMonitor(ttLineCount, data, 0);
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data); 
			prints(" has stopped taking tickets.\n");
			/* Release(outputLock); */
			
			Signal(ttCV[data], ttLock[data]);
			Release(ttLock[data]);
			Wait(lobbyCV, ttLineLock);
			Release(ttLineLock);
			continue;
		} else {
			/* seats is enough */
			/* Acquire(outputLock); */
			prints("TicketTaker "); print(data);
			prints(" is allowing the group into the theater. The number of tickets taken is ");
			print(ReadMonitor(ttTakenSeat, 0));	prints(".\n");
			/* Release(outputLock); */
			
			SetMonitor(ttProcess, data, 1);
			SetMonitor(ttTakenSeat, 0, ReadMonitor(ttTakenSeat, 0) + seats);
			SetMonitor(ttTicketTotal, 0, ReadMonitor(ttTicketTotal, 0) + seats);
			Release(ttLineLock);
		}
		Signal(ttCV[data], ttLock[data]);
		Wait(ttCV[data], ttLock[data]);
		Release(ttLock[data]);
	}

	Exit(0);
}